package com.example.erat.util;

import com.example.erat.dto.StatisticsDTO;
import com.example.erat.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset;

import java.awt.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;

/**
 * 图表工具类 - 单例模式
 * 
 * 质量属性:
 * - 性能(P1, P2): 避免重复创建图表工具实例
 * - 可维护性(M1): 集中管理图表生成逻辑
 */
@Slf4j
public class ChartUtil {

    private static volatile ChartUtil instance;
    
    /**
     * 私有构造函数 - 单例模式
     * 
     * 支持质量属性:
     * - 性能(P2): 控制实例创建
     */
    private ChartUtil() {
        if (instance != null) {
            throw new RuntimeException("使用getInstance()方法获取实例");
        }
    }
    
    /**
     * 获取实例 - 单例模式(双重检查锁定)
     * 
     * 支持质量属性:
     * - 性能(P2): 线程安全的单例实现
     * - 可靠性(R2): 确保线程安全
     * 
     * @return ChartUtil实例
     */
    public static ChartUtil getInstance() {
        if (instance == null) {
            synchronized (ChartUtil.class) {
                if (instance == null) {
                    instance = new ChartUtil();
                }
            }
        }
        return instance;
    }
    
    /**
     * 生成实验提交率折线图
     * 
     * 支持质量属性:
     * - 可用性(U3): 提供可视化统计结果
     * - 性能(P1): 优化图表生成性能
     * 
     * @param statistics 实验统计数据
     * @return 图表字节数组
     */
    public byte[] generateSubmissionRateChart(List<StatisticsDTO.ExperimentStatistics> statistics) {
        // 创建数据集
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        
        // 添加数据点
        for (StatisticsDTO.ExperimentStatistics statistic : statistics) {
            dataset.addValue(
                    statistic.getSubmissionRate() * 100, 
                    "提交率", 
                    statistic.getExperimentName()
            );
        }
        
        // 创建图表
        JFreeChart chart = ChartFactory.createLineChart(
                "实验提交率统计", // 标题
                "实验", // x轴标签
                "提交率(%)", // y轴标签
                dataset, // 数据集
                PlotOrientation.VERTICAL, // 方向
                true, // 是否显示图例
                true, // 是否显示工具提示
                false // 是否生成URL
        );
        
        // 设置图表样式
        chart.setBackgroundPaint(Color.WHITE);
        
        // 导出为图片
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            ChartUtils.writeChartAsPNG(outputStream, chart, 800, 600);
            return outputStream.toByteArray();
        } catch (IOException e) {
            log.error("生成图表失败", e);
            throw new BusinessException("生成图表失败: " + e.getMessage());
        }
    }
    
    /**
     * 生成学生缺交次数柱状图
     * 
     * 支持质量属性:
     * - 可用性(U3): 提供可视化统计结果
     * - 性能(P1): 优化图表生成性能
     * 
     * @param statistics 学生统计数据
     * @param maxStudents 最多显示的学生数
     * @return 图表字节数组
     */
    public byte[] generateStudentMissingCountChart(List<StatisticsDTO.StudentStatistics> statistics, int maxStudents) {
        // 按缺交次数排序
        statistics.sort((s1, s2) -> s2.getMissingCount() - s1.getMissingCount());
        
        // 限制显示的学生数量
        int displayCount = Math.min(statistics.size(), maxStudents);
        List<StatisticsDTO.StudentStatistics> displayStatistics = statistics.subList(0, displayCount);
        
        // 创建数据集
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        
        // 添加数据点
        for (StatisticsDTO.StudentStatistics statistic : displayStatistics) {
            dataset.addValue(
                    statistic.getMissingCount(), 
                    "缺交次数", 
                    statistic.getName() + "(" + statistic.getStudentId() + ")"
            );
        }
        
        // 创建图表
        JFreeChart chart = ChartFactory.createBarChart(
                "学生缺交次数统计", // 标题
                "学生", // x轴标签
                "缺交次数", // y轴标签
                dataset, // 数据集
                PlotOrientation.VERTICAL, // 方向
                true, // 是否显示图例
                true, // 是否显示工具提示
                false // 是否生成URL
        );
        
        // 设置图表样式
        chart.setBackgroundPaint(Color.WHITE);
        
        // 导出为图片
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            ChartUtils.writeChartAsPNG(outputStream, chart, 800, 600);
            return outputStream.toByteArray();
        } catch (IOException e) {
            log.error("生成图表失败", e);
            throw new BusinessException("生成图表失败: " + e.getMessage());
        }
    }
} 